#pragma once

/// @file

#include <string>
#include <functional>
#include <vector>
#include <cstdint>

#include "core/packet.h"

/// packet recall function type
using PacketCallBack = std::function<void(Packet&&)>;

/// Forward declaration.
class DeviceManager;
class PacketDispatcher;

class IDevice {
 public:
    virtual ~IDevice() = default;

    /// basic operation
    virtual bool open(const std::string& deviceName) = 0;
    virtual void close() = 0;
    virtual bool isOpen() const = 0;

    /// packet operation
    virtual bool startCapture() = 0;
    virtual void stopCapture() = 0;
    virtual bool injectPacket(const uint8_t* data, size_t length) = 0;
    virtual bool injectPacket(const Packet& packet) = 0;

    /// filters
    virtual bool setBPFFilter(const std::string& filterExpression) = 0;

    /// dispatcher
    virtual bool setDispatcher(std::shared_ptr<PacketDispatcher> dispatcher) = 0;
    virtual std::shared_ptr<PacketDispatcher> getDispatcher() = 0;

    /// settings
    virtual bool setPromiscuousMode(bool enabled) = 0;
    virtual bool setTimeout(int milliseconds) = 0;
    virtual bool setBufferSize(int size) = 0;
    /// @brief Only head set 68, full packet set 65535.
    virtual bool setSnapshotLength(int snapshot_len) = 0;
    virtual bool setFilter(const std::string& filter) = 0;
    virtual void setPacketCallback(PacketCallBack callback) = 0;

    /// statistics
    virtual uint64_t getPacketReceived() const = 0;
    virtual uint64_t getPacketDropped() const = 0;
    virtual uint64_t getBytesReceived() const = 0;

    /// device information
    virtual std::string getName() const = 0;
    virtual std::string getDescription() const = 0;

 protected:
    /// only friend class can create
    IDevice() = default;

    /// declare a friend class
    friend class DeviceManager;

 private:
    /// deleted copy constructor and assignment
    IDevice(const IDevice&) = delete;
    IDevice& operator=(const IDevice&) = delete;
};